/*
@Time : 2020/12/29 11:48 上午
@Author : chenle
@File : config
@Software: GoLand
*/
package lego

import (
	"fmt"
	"gopkg.in/yaml.v2"
	"io/ioutil"
	"log"
	"os"
	"time"
)

// 初始化系统配置
func (l *Lego) loadConf() {
	SysInfo(">>>>>>>> | config file is loading")
	filename := "/data/service/" + os.Getenv("APP_NAME") + "/conf/sys.yaml"
	exist, err := isFileExist(filename)
	if err != nil {
		log.Fatal(fmt.Errorf("check config file error, err: %v, filename: %s", err, filename))
	}
	if !exist {
		filename = "conf/sys.yaml"
		exist, err = isFileExist(filename)
		if err != nil {
			log.Fatal(fmt.Errorf("check config file error, err: %v, filename: %s", err, filename))
		}
	}

	confValue = &Conf{}
	yamlFile, err := ioutil.ReadFile(filename)
	if err != nil {
		log.Fatal(fmt.Errorf("read config file error, err: %v, filename: %s", err, filename))
	}
	err = yaml.Unmarshal(yamlFile, confValue)
	if err != nil {
		log.Fatal(fmt.Errorf("unmarshal config file error, err: %v, filename: %s", err, filename))
	}

	switch confValue.RunMode {
	case "prod":
		confValue.Env = confValue.Prod
	case "pre":
		confValue.Env = confValue.Pre
	case "debug":
		confValue.Env = confValue.Debug
	case "test":
		confValue.Env = confValue.Test
	case "local":
		confValue.Local.MySQL.Address = os.Getenv("LOCAL_DB_ADDRESS")
		confValue.Local.MySQL.DbName = os.Getenv("LOCAL_DB_NAME")
		confValue.Local.MySQL.Username = os.Getenv("LOCAL_DB_USERNAME")
		confValue.Local.MySQL.Password = os.Getenv("LOCAL_DB_PASSWORD")
		confValue.Local.MySQL.MaxOpenConns = 64
		confValue.Local.MySQL.MaxIdleConns = 16
		confValue.Local.MySQL.ConnMaxLifetime = 36000000
		confValue.Env = confValue.Local

	default:
		confValue.Env = confValue.Test
	}
	l.Engine.Config = confValue

	if confValue.OpenShowDoc {
		l.AddBeforeFilters(ReqHandle)
		l.AddAfterFilters(ShowDocHandle)
	}
	l.Engine.OpenShowDoc = confValue.OpenShowDoc

	SysInfo("<<<<<<<< | config file loaded success")
}

var confValue *Conf

// 获取mysql配置项
func (c *Conf) GetMysqlConf() *MySQLConf {
	return &c.Env.MySQL
}

// 获取cos配置
func (c *Conf) GetCosConf() *COSConf {
	return &c.Env.COS
}

// 获取redis配置项
func (c *Conf) GetRedisConf() *RedisConf {
	return &c.Env.Redis
}

// 获取kafka配置
func GetKafkaConf() *KafkaConf {
	return &confValue.Env.Kafka
}

//Conf config of different environments
type Conf struct {
	AppName string `yaml:"appname"`
	//ProductName  string        `yaml:"productname"`
	//ServerName   string        `yaml:"servername"`
	RunMode     string `yaml:"runmode"`
	LogLever    string `yaml:"loglever"`
	LogPath     string `yaml:"logpath"`
	MultiLog    bool   `yaml:"multilog"`
	OpenShowDoc bool   `yaml:"openshowdoc"`
	UserGorm2   bool   `yaml:"usegorm2"`

	HttpPort     string        `yaml:"httpport"`
	GrpcPort     string        `yaml:"grpcport"`
	ReadTimeout  time.Duration `yaml:"readtimeout"`
	WriteTimeout time.Duration `yaml:"writetimeout"`
	JwtSecret    string        `yaml:"jwtsecret"`
	Local        EnvConf       `yaml:"local"`
	Test         EnvConf       `yaml:"test"`
	Dev          EnvConf       `yaml:"dev"`
	Pre          EnvConf       `yaml:"pre"`
	Prod         EnvConf       `yaml:"prod"`
	Debug        EnvConf       `yaml:"debug"`

	Env EnvConf
}

// EnvConf envirnoment config
type EnvConf struct {
	MySQL      MySQLConf      `yaml:"mysql"`
	Redis      RedisConf      `yaml:"redis"`
	Etcd       EtcdConf       `yaml:"etcd"`
	ES         ESConf         `yaml:"es"`
	COS        COSConf        `yaml:"cos"`
	Account    AccountConf    `yaml:"account"`
	WaterProof WaterProofConf `yaml:"waterProof"`
	Kafka      KafkaConf      `yaml:"kafka"`
	ShowDoc    ShowDocConf    `yaml:"showdoc"`
}

type ShowDocConf struct {
	ApiKey     string `yaml:"apikey"`
	ApiToken   string `yaml:"apitoken"`
	ShowDocUrl string `yaml:"showdocurl"`
}

type MySQLConf struct {
	Address         string `yaml:"address"`
	DbName          string `yaml:"dbname"`
	Username        string `yaml:"username"`
	Password        string `yaml:"password"`
	MaxOpenConns    int    `yaml:"maxconns"`
	MaxIdleConns    int    `yaml:"maxidleconns"`
	ConnMaxLifetime int64  `yaml:"connmaxlifetime"`
}

type KafkaConf struct {
	Hosts []string `yaml:"hosts"`
}

// RedisConf redis config, time unit is ms
type RedisConf struct {
	Host        string        `yaml:"host"`
	Password    string        `yaml:"password"`
	MaxIdle     int           `yaml:"maxIdle"`
	MaxActive   int           `yaml:"maxActive"`
	IdleTimeout time.Duration `yaml:"idleTimeout"`
}

type EtcdConf struct {
	Endpoints   []string `yaml:"endpoints"`
	DialTimeout int64    `yaml:"dialtimeout"`
}

type ESConf struct {
	Endpoints []string `yaml:"endpoints"`
}

type COSConf struct {
	SecretID   string `yaml:"secretid"`
	SecretKey  string `yaml:"secretkey"`
	Appid      string `yaml:"appid"`
	Region     string `yaml:"region"`
	Bucket     string `yaml:"bucket"`
	ExpireTime int64  `yaml:"expiretime"`
	TempDir    string `yaml:"tempdir"`
}

type AccountConf struct {
	FakeCode                     string `yaml:"fakeCode"`
	UseWaterProof                string `yaml:"useWaterProof"`
	SuperAdminRole               string `yaml:"superAdminRole"`
	SystemRole                   string `yaml:"systemRole"`
	FinanceRole                  string `yaml:"financeRole"`
	ThrowRole                    string `yaml:"throwRole"`
	ReportRole                   string `yaml:"reportRole"`
	NoCommunity                  string `yaml:"noCommunity"`
	PermissionSync               string `yaml:"permissionSync"`
	OperatorSuperAdminRole       string `yaml:"operatorSuperAdminRole"`
	OperatorSystemRole           string `yaml:"operatorSystemRole"`
	OperatorAdvertisementManager string `yaml:"operatorAdvertisementManager"`
}
type WaterProofConf struct {
	Action         string `yaml:"action"`
	Version        string `yaml:"version"`
	CaptchaType    int    `yaml:"captchaType"`
	CloudSecretId  string `yaml:"cloudSecretId"`
	CaptchaAppId   int    `yaml:"captchaAppId"`
	AppSecretKey   string `yaml:"appSecretKey"`
	CloudSecretKey string `yaml:"cloudSecretKey"`
	CloudUlr       string `yaml:"cloudUlr"`
}

func (c *Conf) GetEnvConf() (env *EnvConf) {
	//var env *appc.EnvConf
	switch c.RunMode {
	case "prod":
		env = &c.Prod
	case "pre":
		env = &c.Pre
	case "dev":
		env = &c.Dev
	case "test":
		env = &c.Test
	case "local":
		env = &c.Local
	default:
		env = &c.Test
	}
	return env
}

func (c *Conf) GetLogPath() string {
	return c.LogPath
}

func (c *Conf) GetHttpPort() string {
	return c.HttpPort
}

func (c *Conf) GetGrpcPort() string {
	return c.GrpcPort
}

func (c *Conf) GetAccountConf() AccountConf {
	return c.Env.Account
}
func (c *Conf) GetWaterProofConf() WaterProofConf {
	return c.Env.WaterProof
}
func isFileExist(fliename string) (bool, error) {
	_, err := os.Stat(fliename)
	if err == nil {
		return true, nil
	}
	if os.IsNotExist(err) {
		return false, nil
	}
	return false, err
}

//// Logger :
//type Logger interface {
//	Infof(format string, a ...interface{})
//	Warnf(format string, a ...interface{})
//	Errorf(format string, a ...interface{})
//}
